package controllers

import (
	"api-service/models"
	"api-service/services"
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson"
)

type Book struct {
	Title  string `json:"title"`
	Author string `json:"author"`
}

func HanlderInsertT(c *gin.Context) {
	cli := models.GetMongoClient()
	coll := cli.Database("testdb").Collection("books")
	var book Book
	if err := c.ShouldBindJSON(&book); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request payload"})
		return
	}
	fmt.Printf("Request body doc: %+v\n", book)
	result, err := coll.InsertOne(context.TODO(), book)
	if err != nil {
		c.JSON(http.StatusOK, err)
	}

	fmt.Printf("Inserted document with _id: %v\n", result)
	c.JSON(http.StatusOK, result)
}

func HandlerFind(c *gin.Context) {
	cli := models.GetMongoClient()
	coll := cli.Database("testdb").Collection("books")

	// Find all documents in the books collection
	cursor, err := coll.Find(context.TODO(), bson.M{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve books from MongoDB"})
		return
	}
	defer cursor.Close(context.TODO())

	var books []Book
	for cursor.Next(context.TODO()) {
		var book Book
		if err := cursor.Decode(&book); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to decode book from MongoDB"})
			return
		}
		books = append(books, book)
	}

	if err := cursor.Err(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Cursor error"})
		return
	}

	c.JSON(http.StatusOK, books)
}

// 保存图片至Mongodb
func HanlderSavePic(c *gin.Context) {
	// 1. 检查文件是否上传
	file, err := c.FormFile("file")
	if err != nil || file == nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "No file uploaded"})
		return
	}

	// 提取参数 startX, startY, width, height
	var (
		startX, startY, width, height int
		errParse                      error
	)
	startX, errParse = strconv.Atoi(c.PostForm("startX"))
	if errParse != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid or missing parameter 'startX'"})
		return
	}
	startY, errParse = strconv.Atoi(c.PostForm("startY"))
	if errParse != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid or missing parameter 'startY'"})
		return
	}
	width, errParse = strconv.Atoi(c.PostForm("width"))
	if errParse != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid or missing parameter 'width'"})
		return
	}
	height, errParse = strconv.Atoi(c.PostForm("height"))
	if errParse != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid or missing parameter 'height'"})
		return
	}

	// 2. 打开文件
	src, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to open file"})
		return
	}
	defer src.Close()

	// 3. 将文件内容读取为字节数组
	var buffer bytes.Buffer
	if _, err := io.Copy(&buffer, src); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read file content"})
		return
	}
	fileBytes := buffer.Bytes()

	// 4. 调用服务层保存图片
	cli := models.GetMongoClient()
	insertedID, err := services.SavePictureToMongoDB(cli, file.Filename, fileBytes, startX, startY, width, height)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save file to mongodb"})
		return
	}
	fmt.Printf("Result: %+v\n", insertedID)

	// 5. to rabbitmq and return the result
	// 定义一个channel 接受异步返回消息
	resultChan := make(chan map[string]interface{}, 1)

	go func() {
		services.CV_Calculate(insertedID, resultChan)
	}()

	// 等待结果或超时
	select {
	case result := <-resultChan:
		// 返回成功或失败的结果
		c.JSON(http.StatusOK, result)
	case <-time.After(10 * time.Second):
		// 超时处理
		c.JSON(http.StatusGatewayTimeout, gin.H{"error": "Request timed out"})
	}
}
